﻿using System;
using System.Collections.Generic;
using UnityEngine;

namespace BehaviorDesigner.Runtime.Tasks.Basic
{
    [TaskCategory("My/Enemy/Logical")]
    public class UseAttackCard : Action
    {
        public SharedGameObject castCardInstance;
        public SharedGameObject castReceiver;
        
        public override void OnStart()
        {
            // TODO 对着施放的目标使用当前设置的卡牌
            if (BattleResolver.DealWithCardEffect(gameObject, castReceiver.Value, castCardInstance.Value.GetComponent<BasicCard>().pairData.cardData, castReceiver.Value.transform.position))
            {
                return;       
            }
            return;
        }
    }

    [TaskCategory("My/Enemy/Logical")]
    public class DiscardHoldingCards : Action
    {
        public SharedGameObject castCardInstance;
        public DeckType deckType;
        private CardManager _cardManager;

        private BehaviorTree _behaviorTree;
        
        public override void OnAwake()
        {
            _cardManager = GetComponent<BaseEntity>().GetCardManager();
            _behaviorTree = GetComponent<BehaviorTree>();
        }

        public override TaskStatus OnUpdate()
        {
            try
            {
                _cardManager.DiscardCard(castCardInstance.Value, deckType);
                
                _behaviorTree.SetVariable("castReceiver", new SharedGameObject());
                _behaviorTree.SetVariable("castCardInstance", new SharedGameObject());
            }
            catch (Exception e)
            {
                Debug.Log(e);
                return TaskStatus.Failure;
            }

            return TaskStatus.Success;
        }
    }
    
    [TaskCategory("My/Enemy/Logical")]
    public class IsCanUseAttackCard : Conditional
    {
        public SharedGameObject castCardInstance;
        public SharedGameObject castReceiver;

        public override TaskStatus OnUpdate()
        {
            // 判断当前的参数是否设置
            if (castCardInstance == null || castReceiver == null)
            {
                return TaskStatus.Failure;
            }
            // 耗能是否足够
            if (!BattleResolver.IsCardCanUseInBaseInfo(gameObject, castCardInstance.Value))
            {
                return TaskStatus.Failure;
            }
            // 距离是否足够
            if (!BattleResolver.IsReceiverInCardRange(gameObject, castReceiver.Value, castCardInstance.Value, ""))
            {
                return TaskStatus.Failure;
            }
            
            return TaskStatus.Success;
        }
    }

    [TaskCategory("My/Enemy/SetCastReceiver")]
    public class SetCastReceiver : Action
    {
        public SharedGameObject castCardInstance;
        private GameObject castReceiver;

        public override void OnStart()
        {
            base.OnStart();
            
            TargetType targetType = castCardInstance.Value.GetComponent<BasicCard>().pairData.cardData.targetType;

            switch (targetType)
            {
                case TargetType.Self:
                    castReceiver = gameObject;
                    break;
                case TargetType.Target:
                    castReceiver = GameObject.FindGameObjectWithTag(StaticDataManager.PLAYER_TAG);
                    break;
                case TargetType.Range:
                    castReceiver = gameObject;
                    break;
                default:
                    return;
            }
            
            GetComponent<BehaviorTree>().SetVariable("castReceiver", new SharedGameObject() { Value = castReceiver});
        }
    }

    [TaskCategory("My/Card/IsHasCard")]
    public class IsHasCard : Conditional
    {
        public DeckType deckType;
        private CardManager _cardManager;
        public override void OnAwake()
        {
            _cardManager = GetComponent<BaseEntity>().GetCardManager();
        }

        public override TaskStatus OnUpdate()
        {
            var count = _cardManager.cardInstances[deckType].Count 
                        + _cardManager.remainDeckInstances[deckType].Count 
                        + _cardManager.currentDeckInstances[deckType].Count
                        + _cardManager.recycleDeckInstances[deckType].Count;
            
            return count > 0 ? TaskStatus.Success : TaskStatus.Failure;
        }
    }
    
    [TaskCategory("My/Card/IsRemainingCard")]
    public class IsRemainingCard : Conditional
    {
        public DeckType deckType;
        private CardManager _cardManager;
        public override void OnAwake()
        {
            _cardManager = GetComponent<BaseEntity>().GetCardManager();
        }

        public override TaskStatus OnUpdate()
        {
            return _cardManager.remainDeckInstances[deckType].Count > 0 ? TaskStatus.Success : TaskStatus.Failure;
        }
    }
    
    [TaskCategory("My/Card/RecycleDeck")]
    public class RecycleDeck : Action
    {
        public DeckType deckType;
        private CardManager _cardManager;
        
        public override void OnAwake()
        {
            _cardManager = GetComponent<BaseEntity>().GetCardManager();
        }

        public override TaskStatus OnUpdate()
        {
            try
            {
                _cardManager.RecycleCard(deckType);
            }
            catch (Exception e)
            {
                Debug.Log(e);
                return TaskStatus.Failure;
            }

            return TaskStatus.Success;
        }
    }
    
    [TaskCategory("My/Card/PickCard")]
    public class PickCard : Action
    {
        public DeckType deckType;

        private BehaviorTree _bt;
        private CardManager _cardManager;

        public override void OnAwake()
        {
            _bt = GetComponent<BehaviorTree>();
            _cardManager = GetComponent<BaseEntity>().GetCardManager();
        }

        public override TaskStatus OnUpdate()
        {
            try
            {
                _cardManager.PickCardFromRemainDeck(deckType);

                _bt.SetVariable("castCardInstance", new SharedGameObject() { Value = _cardManager.currentDeckInstances[deckType][0] });
            }
            catch (Exception e)
            {
                Debug.Log(e);
                return TaskStatus.Failure;
            }

            return TaskStatus.Success;
        }
    }

    [TaskCategory("My/Tile/CalculateTileScore")]
    public class CalculateTileScore : Action
    {
        public bool isNeedConsiderApproach;
        
        public SharedGameObject castReceiver;
        
        private BattleEnemyEntity enemyEntity;
        
        public override void OnAwake()
        {
            castReceiver = new SharedGameObject() { Value = GameObject.FindGameObjectWithTag(StaticDataManager.PLAYER_TAG) };
            enemyEntity = GetComponent<BattleEnemyEntity>();
            
            GetComponent<BehaviorTree>().SetVariable("targetTileGameObject", new SharedGameObject());
            GetComponent<BehaviorTree>().SetVariable("tiles", new SharedGameObjectList());
        }

        public override TaskStatus OnUpdate()
        {
            try
            {
                enemyEntity.FindSelectableTiles();
                //enemyEntity.CalculateTargetTile();
                
                TileHelper.CalculateTileScore(castReceiver.Value, enemyEntity.entityData.coverScore, enemyEntity.entityData.approachScore);
                TileManager.ShowSelectableTiles();
            }
            catch (Exception e)
            {
                Debug.Log(e);
                return TaskStatus.Failure;
            }

            return TaskStatus.Success;

        }
    }

    [TaskCategory("My/Tile/SetMoveRangeCoveredTile")]
    public class SetMoveRangeCoveredTile : Action
    {
        public SharedGameObjectList tiles;
        
        private float move;
        private Collider2D[] _collider2Ds;
        private List<GameObject> tileList;

        public override void OnAwake()
        {
            tileList = new List<GameObject>();
            
            move = GetComponent<BaseEntity>()._mp_max;
        }

        public override TaskStatus OnUpdate()
        {
            _collider2Ds = Physics2D.OverlapBoxAll(transform.position, new Vector3(move * 2.5f, move * 2.5f), 0f, LayerMask.GetMask(StaticDataManager.TILE_LAYER));

            foreach (Collider2D collider in _collider2Ds)
            {
                if (collider.GetComponent<TileMonoBehaviour>().parentTile)
                {
                    tileList.Add(collider.gameObject);
                }
            }

            // TODO 然后根据分数排序
            tileList.Sort(((tileA, tileB) => -tileA.GetComponent<TileMonoBehaviour>().GetScore().CompareTo(tileB.GetComponent<TileMonoBehaviour>().GetScore())));
            
            tiles = new SharedGameObjectList() { Value = tileList};
            
            GetComponent<BehaviorTree>().SetVariable("tiles", tiles);

            return TaskStatus.Success;
        }
    }

    [TaskCategory("My/IsSharedObjectListSet")]
    public class IsSharedObjectListSet : Conditional
    {
        public SharedGameObjectList sharedObjectList;
        
        public override TaskStatus OnUpdate()
        {
            return sharedObjectList != null ? TaskStatus.Success : TaskStatus.Failure;
        }
    }
    
    [TaskCategory("My/IsSharedGameObjectSet")]
    public class IsSharedGameObjectSet : Conditional
    {
        public SharedGameObject sharedGameObject;
        
        public override TaskStatus OnUpdate()
        {
            return sharedGameObject != null ? TaskStatus.Success : TaskStatus.Failure;
        }
    }

    [TaskCategory("My/Animator/IsAnimatePlaying")]
    public class IsAnimatePlaying : Conditional
    {
        public string animateName;

        private Animator _animator;
        
        public override void OnAwake()
        {
            _animator = GetComponent<Animator>();
        }

        public override TaskStatus OnUpdate()
        {
            if (_animator.GetCurrentAnimatorStateInfo(0).IsName(animateName) &&
                _animator.GetCurrentAnimatorStateInfo(0).normalizedTime >= 1f)
            {
                return TaskStatus.Success;
            }

            return TaskStatus.Failure;
        }
    }
    
    [TaskCategory("My/Tile/SetMoveTargetTile")]
    public class SetMoveTargetTile : Action
    {
        public SharedGameObjectList tiles;
        public SharedGameObject castCardInstance;
        
        public SharedGameObject targetTileGameObject;
        
        private GameObject _bestTile = null;

        private GameObject _player;
        private EnemyEntity _entity;

        public override void OnAwake()
        {
            _entity = GetComponent<EnemyEntity>();
            
            _player = GameObject.FindGameObjectWithTag(StaticDataManager.PLAYER_TAG);
        }

        public override TaskStatus OnUpdate()
        {
            try
            {
                _bestTile = null;
                
                if (tiles.Value.Count == 0)
                {
                    return TaskStatus.Failure;
                }
                
                // 默认是分数倒序
                // 依次判断这个位置是否可以打到对面
                // 可以判断这个点能不能打到人
                // 可以就这个点
                // 然后就是判断距离适不适合
                
                // 如果都不行就直接取第一个点

                foreach (SharedGameObject tile in tiles.Value)
                {
                    if (BattleResolver.IsReceiverInCardRange(tile.Value, _player, castCardInstance.Value, StaticDataManager.PLAYER_LAYER))
                    {
                        _bestTile = tile.Value;
                        break;
                    }
                }
                
                
                if (_bestTile == null)
                {
                    _bestTile = tiles.Value[0];
                }

                if (_bestTile.transform.position == transform.position)
                {
                    return TaskStatus.Success;
                }
                
                targetTileGameObject = new SharedGameObject() { Value = _bestTile };

                _entity.FindPath(_bestTile.GetComponent<TileMonoBehaviour>());
                
                GetComponent<BehaviorTree>().SetVariable("targetTileGameObject", targetTileGameObject);
                
                TileManager.ShowMoveTiles();
                
            }
            catch (Exception e)
            {
                Debug.Log(e);
                return TaskStatus.Failure;
            }

            return TaskStatus.Success;
        }
    }
    
    [TaskCategory("My/EnemyEntity/MoveToTargetTile")]
    public class MoveToTargetTile : Action
    {
        public SharedGameObject targetTileGameObject;

        private EnemyEntity _entity;

        public override void OnAwake()
        {
            _entity = GetComponent<EnemyEntity>();
        }

        public override TaskStatus OnUpdate()
        {
            try
            {
                if (_entity.MoveStep())
                {
                    return TaskStatus.Running;
                }
            }
            catch (Exception e)
            {
                Debug.Log(e);
                return TaskStatus.Failure;
            }
            finally
            {
                targetTileGameObject = null;
            }
            
            return TaskStatus.Success;
        }
    }
}

